﻿using System;

namespace 面向对象_泛型2
{
    class Program
    {
        static void Main(string[] args)
        {
            var a = new List<Base>(6);//new 6个对象
            var b = new List<Son>(5);
            var c = new List<SSon>(6);

            a.Add<Son>(b);
            a.Add<SSon>(c);
            // lst.Add<NSon>(nslt); // 如果 不写 where U:T ，那么这个错误的写法就不报错

            var sc = new SampleClass<Base, int, Base>();
            var scc = new SampleClass<Base, int, Son>();
        }
    }
    // 作为约束的类型参数，换言之：把泛型作为其他泛型的约束
    // list 列表，是集合
    class List<T> where T : Base//这的list跟系统默认list没有任何关系
    {
        private T[] array;//初始化

        public List(int count)//构造函数用来将new T[6]的值赋给array
        {
            array = new T[count];
        }
        public T this[int index]//泛型的索引器
        {
            get { return array[index]; }
        }
        // add :添加
        // 作为约束的类型参数，换言之：把泛型作为其他泛型的约束
        // 表示方法中使用的类型的一种继承关系
        public void Add<U>(List<U> items) where U : T
        {

            // todo 数据拼接就不写了，因为只测试 泛型约束
            // 确实能访问 U 的公共成员，也能访问 T 的公共成员
            var b = items[0];
            Console.WriteLine(b.name);//is中包含了强转并赋值，把as运算符也融入到is中
            if (b is Son s) // is  :是xxx东西
            {
                Console.WriteLine(s.size);
            }
            else if (b is SSon)
            {
                var ss = b as SSon;
                Console.WriteLine(ss.sex);
            }
        }
    }

    class Base
    {
        public string name;
    }
    class Son : Base
    {
        public int size;
    }
    class SSon : Son
    {
        public string sex;
    }
    // 类型声明时，把泛型作为其他泛型的约束
    // 当有多个泛型参数，他们之间也可以满足 泛型作为泛型的约束
    //  以下示例中， 一旦 T 的类型定下来了，那么，V 的类型就定下来了
    class SampleClass<T, U, V> where V : T
    {

    }
}
